package com.props.starter.controller;

import com.props.starter.config.PropsManagementProperties;
import com.props.starter.model.ConfigFile;
import com.props.starter.model.ConfigVersion;
import com.props.starter.service.ConfigFileService;
import com.props.starter.service.VersionService;
import jakarta.annotation.PostConstruct;
import jakarta.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.event.EventListener;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Props Management REST Controller
 * 处理配置文件管理的REST API请求
 */
@RestController
@RequestMapping(produces = MediaType.APPLICATION_JSON_VALUE + ";charset=UTF-8")
@CrossOrigin(origins = "*")
public class PropsManagementController {
    
    private static final Logger log = LoggerFactory.getLogger(PropsManagementController.class);

    private final ConfigFileService configFileService;
    private final VersionService versionService;
    private final PropsManagementProperties properties;

    @Autowired(required = false)
    private ConfigurableEnvironment environment;

    public PropsManagementController(ConfigFileService configFileService, 
                                   VersionService versionService,
                                   PropsManagementProperties properties) {
        this.configFileService = configFileService;
        this.versionService = versionService;
        this.properties = properties;
    }

    @PostConstruct
    public void init() {
        if (environment != null) {
            configFileService.setEnvironment(environment);
        }
    }

    /**
     * 获取管理界面 - 动态路径
     */
    @GetMapping("${props.management.management-path:/props-management}")
    public String index() {
        return "forward:" + properties.getManagementPath() + "/index.html";
    }

    /**
     * 获取所有配置文件列表
     */
    @GetMapping("/api${props.management.management-path:/props-management}/files")
    public ResponseEntity<Map<String, Object>> getConfigFiles() {
        try {
            List<ConfigFile> files = configFileService.getAllConfigFiles();
            Map<String, Object> response = new HashMap<>();
            response.put("success", true);
            response.put("data", files);
            
            log.info("Retrieved {} configuration files", files.size());
            return ResponseEntity.ok()
                    .contentType(MediaType.APPLICATION_JSON)
                    .body(response);
        } catch (Exception e) {
            log.error("Error retrieving config files", e);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                    .contentType(MediaType.APPLICATION_JSON)
                    .body(createErrorResponse("Failed to retrieve config files: " + e.getMessage()));
        }
    }

    /**
     * 获取指定配置文件详情
     */
    @GetMapping("/api${props.management.management-path:/props-management}/files/{fileName}")
    public ResponseEntity<ConfigFile> getConfigFileDetail(@PathVariable("fileName") String fileName) {
        try {
            ConfigFile configFile = configFileService.getConfigFileDetail(fileName);
            if (configFile != null) {
                return ResponseEntity.ok(configFile);
            } else {
                return ResponseEntity.notFound().build();
            }
        } catch (Exception e) {
            log.error("Error getting config file detail for: " + fileName, e);
            return ResponseEntity.internalServerError().build();
        }
    }

    /**
     * 更新配置值
     */
    @PostMapping("/api${props.management.management-path:/props-management}/files/{fileName}/update")
    public ResponseEntity<Map<String, Object>> updateConfigValue(
            @PathVariable("fileName") String fileName,
            @RequestBody Map<String, String> updateRequest) {
        
        Map<String, Object> response = new HashMap<>();
        
        try {
            String key = updateRequest.get("key");
            String value = updateRequest.get("value");
            
            if (key == null || value == null) {
                response.put("success", false);
                response.put("message", "Key and value are required");
                return ResponseEntity.badRequest().body(response);
            }
            
            // 首先检查配置项是否可编辑
            ConfigFile configFile = configFileService.getConfigFileDetail(fileName);
            if (configFile != null && configFile.getEditableFlags() != null) {
                Boolean isEditable = configFile.getEditableFlags().get(key);
                if (isEditable != null && !isEditable) {
                    response.put("success", false);
                    response.put("message", "Configuration '" + key + "' is a startup-time setting and cannot be modified at runtime");
                    response.put("readOnly", true);
                    return ResponseEntity.badRequest().body(response);
                }
            }
            
            boolean success = configFileService.updateConfigValue(fileName, key, value);
            response.put("success", success);
            response.put("message", success ? "Config updated successfully" : "Failed to update config");
            
            return ResponseEntity.ok(response);
            
        } catch (Exception e) {
            log.error("Error updating config value", e);
            response.put("success", false);
            response.put("message", "Internal server error");
            return ResponseEntity.status(500).body(response);
        }
    }

    /**
     * 保存配置文件版本
     */
    @PostMapping("/api${props.management.management-path:/props-management}/files/{fileName}/save")
    public ResponseEntity<Map<String, Object>> saveVersion(
            @PathVariable("fileName") String fileName,
            @RequestBody Map<String, String> saveRequest) {
        
        Map<String, Object> response = new HashMap<>();
        
        try {
            String comment = saveRequest.get("comment");
            if (comment == null || comment.trim().isEmpty()) {
                response.put("success", false);
                response.put("message", "Save comment is required");
                return ResponseEntity.badRequest().body(response);
            }
            
            // 获取当前文件内容
            ConfigFile configFile = configFileService.getConfigFileDetail(fileName);
            if (configFile == null) {
                response.put("success", false);
                response.put("message", "Config file not found");
                return ResponseEntity.status(404).body(response);
            }
            
            ConfigVersion version = versionService.saveVersion(fileName, configFile.getRawContent(), comment.trim());
            
            if (version != null) {
                response.put("success", true);
                response.put("message", "Version saved successfully");
                response.put("version", version);
            } else {
                response.put("success", false);
                response.put("message", "Failed to save version (version management may be disabled)");
            }
            
            return ResponseEntity.ok(response);
            
        } catch (Exception e) {
            log.error("Error saving version", e);
            response.put("success", false);
            response.put("message", "Internal server error");
            return ResponseEntity.status(500).body(response);
        }
    }

    /**
     * 获取配置文件的版本列表
     */
    @GetMapping("/api${props.management.management-path:/props-management}/files/{fileName}/versions")
    public ResponseEntity<List<ConfigVersion>> getVersions(@PathVariable("fileName") String fileName) {
        try {
            List<ConfigVersion> versions = versionService.getVersions(fileName);
            return ResponseEntity.ok(versions);
        } catch (Exception e) {
            log.error("Error getting versions for file: " + fileName, e);
            return ResponseEntity.internalServerError().build();
        }
    }

    /**
     * 获取版本内容
     */
    @GetMapping("/api${props.management.management-path:/props-management}/versions/{versionId}/content")
    public ResponseEntity<Map<String, String>> getVersionContent(@PathVariable("versionId") String versionId) {
        try {
            Map<String, String> versionContent = versionService.getVersionContent(versionId);
            if (versionContent != null) {
                return ResponseEntity.ok()
                        .contentType(MediaType.APPLICATION_JSON)
                        .body(versionContent);
            } else {
                return ResponseEntity.notFound().build();
            }
        } catch (Exception e) {
            log.error("Error getting version content for: " + versionId, e);
            return ResponseEntity.internalServerError().build();
        }
    }

    /**
     * 删除版本
     */
    @DeleteMapping("/api${props.management.management-path:/props-management}/files/{fileName}/versions/{versionId}")
    public ResponseEntity<Map<String, Object>> deleteVersion(
            @PathVariable("fileName") String fileName,
            @PathVariable("versionId") String versionId) {
        
        Map<String, Object> response = new HashMap<>();
        
        try {
            boolean success = versionService.deleteVersion(fileName, versionId);
            response.put("success", success);
            response.put("message", success ? "Version deleted successfully" : "Failed to delete version");
            
            return ResponseEntity.ok(response);
            
        } catch (Exception e) {
            log.error("Error deleting version", e);
            response.put("success", false);
            response.put("message", "Internal server error");
            return ResponseEntity.status(500).body(response);
        }
    }

    /**
     * 获取可嵌入的iframe代码，支持跨域调用
     */
    @GetMapping("/api${props.management.management-path:/props-management}/embed")
    @CrossOrigin(origins = "*", methods = {RequestMethod.GET})
    public ResponseEntity<String> getEmbedCode(HttpServletRequest request,
            @RequestParam(value = "width", defaultValue = "100%") String width,
            @RequestParam(value = "height", defaultValue = "600px") String height,
            @RequestParam(value = "border", defaultValue = "1") String border,
            @RequestParam(value = "title", defaultValue = "Props Management") String title) {
        
        try {
            // 获取当前请求的基础URL
            String scheme = request.getScheme();
            String serverName = request.getServerName();
            int serverPort = request.getServerPort();
            String contextPath = request.getContextPath();
            
            // 构建基础URL
            StringBuilder baseUrl = new StringBuilder();
            baseUrl.append(scheme).append("://").append(serverName);
            if ((scheme.equals("http") && serverPort != 80) || 
                (scheme.equals("https") && serverPort != 443)) {
                baseUrl.append(":").append(serverPort);
            }
            baseUrl.append(contextPath);
            
            // 获取管理路径
            String managementPath = properties.getManagementPath();
            if (managementPath == null) {
                managementPath = "/props-management";
            }
            
            // 构建iframe的src URL
            String iframeUrl = baseUrl.toString() + managementPath + "/index.html";
            
            // 生成iframe HTML代码
            String iframeHtml = String.format(
                "<iframe src=\"%s\" " +
                "width=\"%s\" " +
                "height=\"%s\" " +
                "frameborder=\"%s\" " +
                "title=\"%s\" " +
                "style=\"border: %s solid #ddd; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.1);\" " +
                "allowfullscreen=\"true\" " +
                "sandbox=\"allow-scripts allow-same-origin allow-forms allow-popups allow-popups-to-escape-sandbox\">" +
                "</iframe>",
                iframeUrl, width, height, border, title, border.equals("0") ? "0px" : "1px"
            );
            
            log.info("Generated iframe embed code for URL: {}", iframeUrl);
            
            return ResponseEntity.ok()
                    .contentType(MediaType.TEXT_HTML)
                    .header("Access-Control-Allow-Origin", "*")
                    .header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
                    .header("Access-Control-Allow-Headers", "Content-Type, Authorization")
                    .body(iframeHtml);
            
        } catch (Exception e) {
            log.error("Error generating embed code", e);
            String errorHtml = "<div style=\"color: red; padding: 10px; border: 1px solid red; border-radius: 4px;\">" +
                             "Error generating Props Management embed code: " + e.getMessage() + 
                             "</div>";
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                    .contentType(MediaType.TEXT_HTML)
                    .body(errorHtml);
        }
    }

    /**
     * 获取嵌入代码的JSON格式响应，便于JavaScript调用
     */
    @GetMapping("/api${props.management.management-path:/props-management}/embed-json")
    @CrossOrigin(origins = "*", methods = {RequestMethod.GET})
    public ResponseEntity<Map<String, Object>> getEmbedCodeJson(HttpServletRequest request,
            @RequestParam(value = "width", defaultValue = "100%") String width,
            @RequestParam(value = "height", defaultValue = "600px") String height,
            @RequestParam(value = "border", defaultValue = "1") String border,
            @RequestParam(value = "title", defaultValue = "Props Management") String title) {
        
        Map<String, Object> response = new HashMap<>();
        
        try {
            // 获取当前请求的基础URL
            String scheme = request.getScheme();
            String serverName = request.getServerName();
            int serverPort = request.getServerPort();
            String contextPath = request.getContextPath();
            
            // 构建基础URL
            StringBuilder baseUrl = new StringBuilder();
            baseUrl.append(scheme).append("://").append(serverName);
            if ((scheme.equals("http") && serverPort != 80) || 
                (scheme.equals("https") && serverPort != 443)) {
                baseUrl.append(":").append(serverPort);
            }
            baseUrl.append(contextPath);
            
            // 获取管理路径
            String managementPath = properties.getManagementPath();
            if (managementPath == null) {
                managementPath = "/props-management";
            }
            
            // 构建iframe的src URL
            String iframeUrl = baseUrl.toString() + managementPath + "/index.html";
            
            // 生成iframe HTML代码
            String iframeHtml = String.format(
                "<iframe src=\"%s\" " +
                "width=\"%s\" " +
                "height=\"%s\" " +
                "frameborder=\"%s\" " +
                "title=\"%s\" " +
                "style=\"border: %s solid #ddd; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.1);\" " +
                "allowfullscreen=\"true\" " +
                "sandbox=\"allow-scripts allow-same-origin allow-forms allow-popups allow-popups-to-escape-sandbox\">" +
                "</iframe>",
                iframeUrl, width, height, border, title, border.equals("0") ? "0px" : "1px"
            );
            
            response.put("success", true);
            response.put("iframeHtml", iframeHtml);
            response.put("iframeUrl", iframeUrl);
            response.put("managementPath", managementPath);
            response.put("baseUrl", baseUrl.toString());
            
            log.info("Generated iframe embed JSON for URL: {}", iframeUrl);
            
            return ResponseEntity.ok()
                    .contentType(MediaType.APPLICATION_JSON)
                    .header("Access-Control-Allow-Origin", "*")
                    .header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
                    .header("Access-Control-Allow-Headers", "Content-Type, Authorization")
                    .body(response);
            
        } catch (Exception e) {
            log.error("Error generating embed JSON", e);
            response.put("success", false);
            response.put("message", "Error generating embed code: " + e.getMessage());
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                    .contentType(MediaType.APPLICATION_JSON)
                    .body(response);
        }
    }

    private Map<String, Object> createErrorResponse(String message) {
        Map<String, Object> response = new HashMap<>();
        response.put("success", false);
        response.put("message", message);
        return response;
    }
} 